package pt.inescid.components.gui;

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.ArrayList;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import pt.inescid.components.commons.FrontEnd;
import pt.inescid.core.GridP2P;



/**
 * @author Sergio Esteves (sesteves at gsd.inesc-id.pt)
 *
 */
public class GUI extends FrontEnd {		
	
	private JTextArea status = new JTextArea("Status:",4,35);
	private int outputCounter = 0;
	private int lboundHour, uboundHour;
	private long maxStorage;
	private long idleTime;
	private boolean isZero;
	private Object idleTimeObj = new Object();
	
	public GUI(GridP2P gridP2P, int lboundHour, int uboundHour, long idleTime, long maxStorage) {
		super(gridP2P);
		this.lboundHour = lboundHour;
		this.uboundHour = uboundHour;
		this.idleTime = idleTime;
		isZero = idleTime == 0;
		this.maxStorage = maxStorage;
	}
	
	@Override
	public void init() {		
		Runnable runnable = new Runnable() {
			public void run() {
				boolean idle = false, sleep;
				Point previous = null, current;
				long startTick = System.currentTimeMillis();
				while(true) {
					synchronized(idleTimeObj) {
						sleep = isZero;
					}					
					if(sleep) {
						try {
							Thread.sleep(60000);
						} catch (InterruptedException e) {
						}
						continue;
					}
					current = MouseInfo.getPointerInfo().getLocation();
					if(!current.equals(previous)) {
						previous = current;
						startTick = System.currentTimeMillis();
						// I'm not idle
						idle = false;
						gridP2P.setIsIdle(false);
					} else {
						synchronized(idleTimeObj) {
							if(!idle && (System.currentTimeMillis() - startTick >= idleTime)) {
								// I'm idle
								idle = true;
								gridP2P.setIsIdle(true);
							}
						}
					}
					try {
						Thread.sleep(3000);
					} catch (InterruptedException e) {
					}
				}
			}
		};		
		
		// status	
		JScrollPane sp = new JScrollPane(status);		
		
		// frame
		final JFrame frame = new JFrame("GridP2P");
		frame.setLayout(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// icon
	    frame.setIconImage(Toolkit.getDefaultToolkit().getImage("gsdico.gif"));		
		
	    // frames
	    final JInternalFrame frameAdd = new JInternalFrame("Internal frame", true,true,true,true);	    

		//JLabel  label = new JLabel("Swing Version");
	    // storage
	    JLabel lblStorage1 = new JLabel("Use no more than: ");	
	    SpinnerModel sm = new SpinnerNumberModel(maxStorage / 1048576, 0, 1000, 1);
	    JSpinner spnStorage = new JSpinner(sm);
	    JLabel lblStorage2 = new JLabel("MB of disk space");
	    
	    // policies
	    JLabel lblDoWork1 = new JLabel("Do work only between: ");
	    String str[] = {"Anytime","0:00","1:00","2:00","3:00","4:00","5:00","6:00","7:00",
	    		"8:00","9:00","10:00","11:00","12:00","13:00","14:00","15:00","16:00","17:00",
	    		"18:00","19:00","20:00","21:00","22:00","23:00"};
	    final JComboBox cmbDoWork1 = new JComboBox(str);
	    cmbDoWork1.setSelectedIndex(lboundHour < 0 ? 0 : lboundHour + 1);
	    JLabel lblDoWork2 = new JLabel("and");
	    String str3[] = {"0:00","1:00","2:00","3:00","4:00","5:00","6:00","7:00",
	    		"8:00","9:00","10:00","11:00","12:00","13:00","14:00","15:00","16:00","17:00",
	    		"18:00","19:00","20:00","21:00","22:00","23:00"};
	    final JComboBox cmbDoWork2 = new JComboBox(str3);
	    cmbDoWork2.setSelectedIndex(uboundHour);
	    JLabel lblIdle1 = new JLabel("Do work after idle for: ");
	    SpinnerModel sm2 = new SpinnerNumberModel(idleTime / 60000, 0, 1000, 1);
	    JSpinner spnIdle = new JSpinner(sm2);
	    JLabel lblIdle2 = new JLabel("minutes (0 = anytime)");
	    
	    JPanel pnlPolicies = new JPanel(new FlowLayout());
	    pnlPolicies.setBorder(BorderFactory.createTitledBorder("Configurations"));
	    pnlPolicies.add(lblDoWork1);
	    pnlPolicies.add(cmbDoWork1);
	    pnlPolicies.add(lblDoWork2);
	    pnlPolicies.add(cmbDoWork2);
	    
	    pnlPolicies.add(lblIdle1);
	    pnlPolicies.add(spnIdle);
	    pnlPolicies.add(lblIdle2);	    
	    
	    pnlPolicies.add(lblStorage1);
	    pnlPolicies.add(spnStorage);
	    pnlPolicies.add(lblStorage2);
	    
	    final JFileChooser inputChooser = new JFileChooser();
	    
	    final JFileChooser outputChooser = new JFileChooser();
	    inputChooser.setMultiSelectionEnabled(true);
	    inputChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
	    File f = new File(System.getProperty("user.dir"));
	    inputChooser.setCurrentDirectory(f);	   
	    outputChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
	    outputChooser.setCurrentDirectory(f);
	    
//		JLabel lblWorkingDir = new JLabel("Working Dir:");
//		JTextField fieldWorkingDir = new JTextField(20);
	    
		JLabel lblOutput = new JLabel("Destination:");
		final JTextField fieldOutput = new JTextField(20);	
		
		
		JLabel lblInput = new JLabel("Input File(s):");
		final JTextField fieldInput = new JTextField(20);
		
		// ComboBox
		JLabel lblAppList = new JLabel("Application:");
		String[] appIds = null;
		if(gridP2P != null)
			appIds = gridP2P.getAppIDs();
		final JComboBox appList = new JComboBox(
				appIds == null ? new String[]{"No applications"} : appIds);
		
		//appList.setSelectedIndex(4);
		//appList.addActionListener(this);
		
		// Buttons
		JButton btnSubmit = new JButton("Submit Job");
		JButton btnExit = new JButton ("Exit");
		JButton btnAdd = new JButton("Add...");
		JButton btnBrowseInput = new JButton("Browse...");
		JButton btnBrowseOutput = new JButton("Browse...");
				
		// Listeners 
		cmbDoWork1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt)
			{
				String str = (String)cmbDoWork1.getSelectedItem();
				int hour = str.startsWith("A") ? -1 : Integer.parseInt(str.split(":")[0]);
				gridP2P.setLboundHour(hour);
			}	
		});
		cmbDoWork2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt)
			{
				String str = (String)cmbDoWork2.getSelectedItem();
				int hour = Integer.parseInt(str.split(":")[0]);
				gridP2P.setUboundHour(hour);
			}	
		});
		
		sm.addChangeListener(new ChangeListener() {
			public void stateChanged (ChangeEvent e) {
				Double value = (Double)((SpinnerModel)e.getSource()).getValue();				
				gridP2P.setMaxStorage(value.longValue() * 1048576);
			}
		});

		sm2.addChangeListener(new ChangeListener() {
			public void stateChanged (ChangeEvent e) {
				Double value = (Double)((SpinnerModel)e.getSource()).getValue();
				synchronized(idleTimeObj) {					
					idleTime = value.longValue() * 60000;
					isZero = idleTime == 0;
					gridP2P.setIsIdle(isZero);					
				}				
			}
		});
		
		btnBrowseInput.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt)
			{
				if(inputChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
					File files[] = inputChooser.getSelectedFiles();
					if(files.length != 2) {
						fieldInput.setText("You need to pick a config file and a data file!");
						return;
					}
					fieldInput.setText(files[0].toString().replace('\\', '/') + ";" + 
							files[1].toString().replace('\\', '/'));
				}
			}	
		});
		btnBrowseOutput.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt)
			{
				if(outputChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION)					
					fieldOutput.setText(
							outputChooser.getSelectedFile().getAbsolutePath().replace('\\', '/') + 
							"/output" + outputCounter++ + ".ppm");
			}	
		});		
		btnExit.addActionListener( new ActionListener() {
			public void actionPerformed(ActionEvent evt)
			{
				System.exit(0);
			}
		});

		btnAdd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				frameAdd.setSize(250,300);
				frameAdd.setVisible(true);
			}
		});
		
		btnSubmit.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				ArrayList<String> input = new ArrayList<String>();
				String str[] = fieldInput.getText().split(";");
				for(int i = 0; i < str.length; i++)
					input.add(str[i]);
				gridP2P.createJob((String)appList.getSelectedItem(), input, fieldOutput.getText());
			}
		});
		
		// Applications ListBox
		// appListBox.set
	    
		// Get content pane
		Container pane = frame.getContentPane();

		// Set layout manager
		pane.setLayout(new FlowLayout());
	
		// Add to pane	
		pane.add(btnSubmit);
		pane.add(btnExit);
		pane.add(btnAdd);
		
		//pane.add(lblWorkingDir);
		//pane.add(fieldWorkingDir);		
		
		pane.add(lblInput);
		pane.add(fieldInput);
		pane.add(btnBrowseInput);
		
		pane.add(lblOutput);
		pane.add(fieldOutput);
		pane.add(btnBrowseOutput);
		
		pane.add(lblAppList);
		pane.add(appList);
		
		/* storage
		pane.add(lblStorage1);
		pane.add(spnStorage);
		pane.add(lblStorage2);
		
		// policies
		pane.add(lblDoWork1);
		pane.add(cmbDoWork1);
		pane.add(lblDoWork2);
		pane.add(cmbDoWork2);
		
		pane.add(lblIdle1);
		pane.add(cmbIdle);
		pane.add(lblIdle2);
		*/
		pane.add(pnlPolicies);		
		pane.add(sp);		
		pane.add(frameAdd);				
		frame.pack();

		// Center the frame
		Toolkit toolkit = Toolkit.getDefaultToolkit();

		// Get the current screen size
		Dimension scrnsize = toolkit.getScreenSize();

		// Get the frame size
		//Dimension framesize= frame.getSize();
		
		// Set the frame size
		frame.setSize(430,450);
		
		// Set X,Y location
		frame.setLocation ((int)(scrnsize.getWidth() - frame.getWidth()) / 2 ,
				(int)(scrnsize.getHeight() - frame.getHeight()) / 2);					
		
		pane.setLayout(null);
		
		// Buttons
		btnSubmit.setLocation(150, 130);
		btnExit.setLocation(320, 130);
		btnAdd.setLocation(320, 10);
		
		// Application List
		lblAppList.setLocation(10,10);
		appList.setBounds(80,10,200,appList.getHeight());
		
		// Input
		lblInput.setLocation(10, 50);
		fieldInput.setLocation(80, 50);
		btnBrowseInput.setLocation(320,50);
		
		// Output
		lblOutput.setLocation(10, 90);
		fieldOutput.setLocation(80, 90);
		btnBrowseOutput.setLocation(320, 90);
		
		// Policies Panel		
		pnlPolicies.setLocation(10, 170);
		pnlPolicies.setSize(380, 160);
		pnlPolicies.setLayout(null);
		
		// doWork
		lblDoWork1.setLocation(10, 30);
		cmbDoWork1.setLocation(150, 30);
		lblDoWork2.setLocation(240, 30);
		cmbDoWork2.setLocation(280, 30);
		
		// idle
		lblIdle1.setLocation(10, 80);
		spnIdle.setLocation(140, 80);
		lblIdle2.setLocation(220, 80);
		
		// storage
		lblStorage1.setLocation(10, 130);
		spnStorage.setLocation(120, 130);
		lblStorage2.setLocation(200, 130);
		
		// status
		sp.setLocation(10,340);
		
		frame.setVisible(true);		
		new Thread(runnable).start();
	}
	
	@Override
	public void writeln(String str) {
		status.setText(status.getText() + '\n' + str);
	}
}